跳至主要内容

Minimizing Coins

題目

nn 種幣值,最少可以用幾個硬幣湊出 xx 元 ?

輸入

第一行有兩個整數 nnxx,分別代表幣值的數量以及目標要湊出多少錢。

第二行有 nn 個相異正整數 cic_i,代表每種幣值。

  • 1n1001 \le n \le 100
  • 1x1061 \le x \le 10^6
  • 1ci1061 \le c_i \le 10^6

輸出

最少需要多少個硬幣才能湊出 xx 元 ?

若沒有辦法湊出 xx 元,輸出 1-1

範例測資

Input:
3 11
1 5 7

Output:
3

1+5+5=111 + 5 + 5 = 11

33 個硬幣湊出 1111

想法

舉個例子,假設有其中一種幣值為 55,且要湊出 1212 元,那麼我們可以得知湊出 1212 元的方法是湊出 77 元所需要的硬幣數量再加一(加上剛剛的 55 元),或是原本有更好的方案可以湊出 1212 元就保留原本的方案。

狀態定義

dpjdp_{j} 的狀態為湊出 jj 元所需要的最少硬幣數量

狀態轉移

枚舉每一種幣值,若能夠湊出 jcij - c_i 元,那麼可以推得轉移式為 dpj=min(dpj,dpjci+1)dp_{j} = \min(dp_{j}, dp_{j - c_i} + 1) ,因為我們可以多花一個幣值為 cic_i 的硬幣讓金額從 jcij - c_i 變成 jj

Note 1: 注意 jcij - c_i 是否小於 00

Note 2: 初始狀態為 dp0=0dp_{0} = 0,因為湊出總合為 00 需要 00 個硬幣

範例程式碼

C++ 範例
#include<bits/stdc++.h>
#define int long long
#define IO ios_base::sync_with_stdio(0), cin.tie(0)
using namespace std;
signed main() {
IO;
int n, x;
cin >> n >> x;
int c[n];
for(int i = 0; i < n; i++) {
cin >> c[i];
}
int dp[x + 1];
for(int i = 1; i <= x; i++) {
dp[i] = -1;
}
dp[0] = 0;
for(int i = 1; i <= x; i++) {
for(int j = 0; j < n; j++) {
if(i - c[j] >= 0) {
if(dp[i - c[j]] != -1) {
if(dp[i] == -1) {
dp[i] = dp[i - c[j]] + 1;
}
else {
dp[i] = min(dp[i], dp[i - c[j]] + 1);
}
}
}
}
}
cout << dp[x];
}